docs: def accepts_numpy(func):
      """ Allows the first input to be a numpy array and get result in numpy form """
      #@ignores_exc_tb
      #@wraps(func)
      def wrp_accepts_numpy(self, input_, *args, **kwargs):
          if not (util_type.HAVE_NUMPY and isinstance(input_, np.ndarray)):
              # If the input is not numpy, just call the function
              return func(self, input_, *args, **kwargs)
          else:
              # TODO: use a variant of util_list.unflat_unique_rowid_map
              # If the input is a numpy array, and return the output with the same
              # shape as the input
              if UNIQUE_NUMPY:
                  # Remove redundant input (because we are passing it to SQL)
                  input_list, inverse_unique = np.unique(input_, return_inverse=True)
              else:
                  input_list = input_.flatten()
              # Call the function in list format
              # TODO: is this necessary?
              input_list = input_list.tolist()
              output_list = func(self, input_list, *args, **kwargs)
              # Put the output back into numpy
              if UNIQUE_NUMPY:
                  # Reconstruct redundant queries
                  output_arr = np.array(output_list)[inverse_unique]
                  output_shape = tuple(list(input_.shape) + list(output_arr.shape[1:]))
                  return np.array(output_arr).reshape(output_shape)
              else:
                  return np.array(output_list).reshape(input_.shape)
      wrp_accepts_numpy = preserve_sig(wrp_accepts_numpy, func)
      return wrp_accepts_numpy