code: def get_numerical_gradient(f, tensors, delta=1e-5):
      """
      sum all of f's elements to make the last layer error as one
      """
      # buffer for gradients
      gradients = []
      for i in range(len(tensors)):
          tensors[i] = tensors[i].astype(np.float64)
          gradients.append(np.zeros(tensors[i].shape))
  
      # iterate throuth each tensor
      for tensor, gradient in zip(tensors, gradients):
          tensor_flat = tensor.reshape((-1,))
          gradient_flat = gradient.reshape((-1,))
  
          # iterate throuth each element
          for idx in range(len(tensor_flat)):
              # backup
              backup = tensor_flat[idx]
              # increment
              tensor_flat[idx] = tensor_flat[idx] + delta
              f_inc = np.sum(f(np, *tensors))
              # decrement
              tensor_flat[idx] = backup - delta
              f_dec = np.sum(f(np, *tensors))
              # recover
              tensor_flat[idx] = backup
              # gradient
              gradient_flat[idx] = (f_inc - f_dec) / (2.0 * delta)
  
      return gradients
  
file_path: neon/tests/test_backend_autodiff.py
imports: from builtins import zip
  import itertools
  import numpy
  from neon import NervanaObject
  from neon.backends.autodiff import Autodiff
  from utils import call_func, gen_backend_tensors, tensors_allclose
  import pytest
label_desc: Use image node_id 2 for calling a global function with example usage: get_numerical_gradient(f, tensors, delta) and returns: gradients