'get autodiff grads from optree string expression
f_str: the string of expression to be executed
tensors: numpy tensor vals'

def _get_autodiff_grads_and_val(self, f_str, tensor_vals, get_op_tree=False, next_error=None):

    be = self.be
    count = 0
    tensors = []
    for tensor_val in tensor_vals:
        exec ('x%s    =    self.be.array(tensor_val,    name="x%s",    dtype=self.dtype)' % (count, count))
        exec ('tensors.append(x%s)' % count)
        count += 1
    f = None
    f = eval(f_str)
    f_val = be.empty(f.shape)
    f_val[:] = f
    if (next_error is not None):
        next_error = self.be.array(next_error)
    ad = Autodiff(f, be, next_error=next_error)
    if get_op_tree:
        gradients = list(ad.get_grad_op_tree(tensors))
    else:
        gradients = list(ad.get_grad_asnumpyarray(tensors))
    return [gradients, f_val.get()]
