class_docstr: Base class to test Blockwise works for specific Ops
class_docstr_tok: ["Base","class","to","test","Blockwise","works","for","specific","Ops"]
code: def test_grad(self):
      base_inputs = [
          tensor(shape=(None,) * len(param_sig))
          for param_sig in self.params_sig
      ]
      out = self.core_op(*base_inputs).sum()
      # Create separate numpy vectorized functions for each input
      np_funcs = []
      for i, inp in enumerate(base_inputs):
          core_grad_func = pytensor.function(
              base_inputs, grad(out, wrt=inp)
          )
          params_sig = self.signature.split("->")[0]
          param_sig = f"({','.join(self.params_sig[i])})"
          grad_sig = f"{params_sig}->{param_sig}"
          np_func = np.vectorize(core_grad_func, signature=grad_sig)
          np_funcs.append(np_func)
  
      # We test gradient wrt to one batched input at a time
      for test_input_idx in range(len(base_inputs)):
          for (
              vec_inputs,
              vec_inputs_testvals,
          ) in self.create_batched_inputs(batch_idx=test_input_idx):
              out = self.block_op(*vec_inputs).sum()
              pt_func = pytensor.function(
                  vec_inputs, grad(out, wrt=vec_inputs[test_input_idx])
              )
              pt_out = pt_func(*vec_inputs_testvals)
              np_out = np_funcs[test_input_idx](*vec_inputs_testvals)
              np.testing.assert_allclose(
                  pt_out,
                  np_out,
                  rtol=1e-7 if config.floatX == "float64" else 1e-5,
                  atol=1e-6 if config.floatX == "float64" else 1e-4,
              )
  
imports: import re
  from itertools import product
  from typing import Optional, Union
  import numpy
  import pytest
  import pytensor
  from pytensor import config, function
  from pytensor.compile import get_mode
  from pytensor.gradient import grad
  from pytensor.graph import Apply, Op
  from pytensor.graph.replace import vectorize_node
  from pytensor.raise_op import assert_op
  from pytensor.tensor import diagonal, log, tensor
  from pytensor.tensor.blockwise import Blockwise, vectorize_node_fallback
  from pytensor.tensor.nlinalg import MatrixInverse
  from pytensor.tensor.rewriting.blas import specialize_matmul_to_batched_dot
  from pytensor.tensor.slinalg import Cholesky, Solve, cholesky, solve_triangular
  from pytensor.tensor.utils import _parse_gufunc_signature
label_desc: Use image node_id 6 for calling the BlockwiseOpTester obj's underlying member method code with example usage: obj.test_grad() without return types