code: def compute_analytical_and_numerical_grad_graph(
      terminal, inputs, epsilon=1e-3, recompute_graph=True
  ):
      def set_inputs(x0):
          begin = 0
          for i in inputs:
              end = begin + i.size
              i.d = x0[begin:end].reshape(i.shape)
              begin = end
  
      def func(x0):
          set_inputs(x0)
          terminal.forward()
          return terminal.d.copy()
  
      def grad(x0):
          set_inputs(x0)
          backups = [i.g.copy() for i in inputs]
          if recompute_graph:
              terminal.forward()
              terminal.backward()
          gx0 = []
          for i, b in zip(inputs, backups):
              if recompute_graph:
                  gx0.append((i.g.copy() - b).flatten())
              else:
                  gx0.append(i.g.copy().flatten())
              i.g = b
          return np.concatenate(gx0)
  
      inputs0 = np.concatenate([i.d.flatten() for i in inputs])
      analytical_grad = grad(inputs0)
      from scipy.optimize import approx_fprime
  
      numerical_grad = approx_fprime(inputs0, func, epsilon)
      return analytical_grad, numerical_grad
  
imports: from nnabla.utils import nnabla_pb2
  from six.moves import filter
  import copy
  import nnabla
  import nnabla.ext_utils
  import nnabla.functions
  import nnabla.utils.converter
  import nnabla.dtypes
  from nnabla.testing import assert_allclose
  import numpy
  import numpy
  import platform
label_desc: Use image node_id 8 for calling a global function with example usage: compute_analytical_and_numerical_grad_graph(terminal, inputs, epsilon, recompute_graph) and returns: analytical_grad,  numerical_grad, terminal, np