gradients(f, xs, dy, allowNoGradients = false) {
        _util.assert(xs.length > 0, ()=>"gradients() received an empty list of xs.");
        if (dy != null && dy.dtype !== "float32") throw new Error(`dy must have 'float32' dtype, but has '${dy.dtype}'`);
        const y = this.scopedRun(()=>this.startTape(), ()=>this.endTape(), ()=>this.tidy("forward", f));
        _util.assert(y instanceof (0, _tensor.Tensor), ()=>"The result y returned by f() must be a tensor.");
        // Filter out the nodes that don't connect x => y.
        const filteredTape = (0, _tape.getFilteredNodesXToY)(this.state.activeTape, xs, y);
        if (!allowNoGradients && filteredTape.length === 0 && xs.length > 0) throw new Error("Cannot compute gradient of y=f(x) with respect to x. Make sure that the f you passed encloses all operations that lead from x to y.");
        return this.tidy("backward", ()=>{
            const accumulatedGradientMap = {};
            accumulatedGradientMap[y.id] = dy == null ? ones(y.shape) : dy;
            // Backprop gradients through the filtered nodes.
            (0, _tape.backpropagateGradients)(accumulatedGradientMap, filteredTape, // Pass the tidy function to avoid circular dep with `tape.ts`.
            (f)=>this.tidy(f), // Pass an add function to avoide a circular dep with `tape.ts`.
            add);
            const grads = xs.map((x)=>accumulatedGradientMap[x.id]);
            if (this.state.gradientDepth === 0) {
                // This means that we are not computing higher-order gradients
                // and can clean up the tape.
                this.state.activeTape.forEach((node)=>{
                    for (const tensor of node.saved)tensor.dispose();
                });
                this.state.activeTape = null;
            }
            return {
                value: y,
                grads
            };
        });
    }
Returns gradients of `f` with respect to each of the `xs`. The gradients
returned are of the same length as `xs`, but some might be null if `f`
was not a function of that `x`. It also takes optional dy to multiply the
gradient, which defaults to `1`.