function valueAndGrads(f) {
	  assert(isFunction(f), function () {
	    return 'The f passed in valueAndGrads(f) must be a function';
	  });
	  return function (args, dy) {
	    assert(Array.isArray(args) && args.every(function (arg) {
	      return arg instanceof Tensor;
	    }), function () {
	      return 'The args passed in valueAndGrads(f)(args) must be array of ' + 'tensors';
	    });
	    assert(dy == null || dy instanceof Tensor, function () {
	      return 'The dy passed in valueAndGrads(f)(args, dy) must be a tensor';
	    });
	    var res = ENGINE.gradients(function () {
	      return f.apply(void 0, args);
	    }, args, dy);

	    if (dy != null) {
	      assertShapesMatch(res.value.shape, dy.shape, 'The shape of dy passed in valueAndGrads(f)([x1,...], dy) must ' + 'match the shape returned by f([x1,...])');
	    }

	    checkGrads(res.grads);
	    return res;
	  };
	}
Like `tf.grads`, but returns also the value of `f()`. Useful when `f()`
returns a metric you want to show.

The result is a rich object with the following properties:
- grads: The gradients of `f()` w.r.t each input (result of `tf.grads`).
- value: The value returned by `f(x)`.

```js
// f(a, b) = a * b
const f = (a, b) => a.mul(b);
// df/da = b, df/db = a
const g = tf.valueAndGrads(f);

const a = tf.tensor1d([2, 3]);
const b = tf.tensor1d([-2, -3]);
const {value, grads} = g([a, b]);

const [da, db] = grads;

console.log('value');
value.print();

console.log('da');
da.print();
console.log('db');
db.print();
```

@doc {heading: 'Training', subheading: 'Gradients'}