docs: def delete_last(self, num_to_delete=1):
          """ Deletes the last N datapoints from the dataset.
  
          Parameters
          ----------
          num_to_delete : int
              the number of datapoints to remove from the end of the dataset
          """
          # check access level
          if self._access_mode == READ_ONLY_ACCESS:
              raise ValueError('Cannot delete datapoints with read-only access')
  
          # check num to delete
          if num_to_delete > self._num_datapoints:
              raise ValueError('Cannot remove more than the number of datapoints in the dataset')
  
          # compute indices
          last_datapoint_ind = self._num_datapoints - 1
          last_tensor_ind = last_datapoint_ind // self._datapoints_per_file
          new_last_datapoint_ind = self._num_datapoints - 1 - num_to_delete
          new_num_datapoints = new_last_datapoint_ind + 1
  
          new_last_datapoint_ind = max(new_last_datapoint_ind, 0)
          new_last_tensor_ind = new_last_datapoint_ind // self._datapoints_per_file
  
          # delete all but the last tensor
          delete_tensor_ind = range(new_last_tensor_ind+1, last_tensor_ind+1) 
          for tensor_ind in delete_tensor_ind:
              for field_name in self.field_names:
                  filename = self.generate_tensor_filename(field_name, tensor_ind)
                  os.remove(filename)
  
          # update last tensor
          dataset_empty = False
          target_tensor_size = new_num_datapoints % self._datapoints_per_file
          if target_tensor_size == 0:
              if new_num_datapoints > 0:
                  target_tensor_size = self._datapoints_per_file
              else:
                  dataset_empty = True
  
          for field_name in self.field_names:
              new_last_tensor = self.tensor(field_name, new_last_tensor_ind)
              while new_last_tensor.size > target_tensor_size:
                  new_last_tensor.delete_last()
              filename = self.generate_tensor_filename(field_name, new_last_tensor_ind)
              new_last_tensor.save(filename, compressed=True)
              if not new_last_tensor.has_data:
                  os.remove(filename)
                  new_last_tensor.reset()
          
          # update num datapoints            
          if self._num_datapoints - 1 - num_to_delete >= 0:
              self._num_datapoints = new_num_datapoints
          else:
              self._num_datapoints = 0
  
          # handle deleted tensor
          self._num_tensors = new_last_tensor_ind + 1
          if dataset_empty:
              self._num_tensors = 0