nd4j-backends/nd4j-api-parent/nd4j-api/src/main/java/org/nd4j/autodiff/samediff/SameDiff.java
public Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> execBackwards() {

        final SameDiff outer = this;
        if (getFunction("grad") == null)
            defineFunction("grad", new SameDiffFunctionDefinition() {

                @Override
                public SDVariable[] define(SameDiff sameDiff, Map<String, INDArray> inputs, SDVariable[] variableInputs) {
                    //propagate graph to this samediff instance
                    //which will also contain the backward
                    if (SameDiff.this.debugMode) {
                        sameDiff.enableDebugMode();
                    }

                    outer.invokeGraphOn(sameDiff);

                    List<DifferentialFunction> allFunctions = new ArrayList<>(sameDiff.functionInstancesById.values());
                    if (allFunctions.isEmpty()) {
                        throw new ND4JIllegalStateException("No ops found!");
                    }


                    for (val func : allFunctions) {
                        if (func instanceof SDVariable) {
                            continue;
                        }

                        val args = func.args();
                        for (val arg : args)
                            arg.setSameDiff(sameDiff);
                        val outputs = func.outputVariables();
                        for (val output : outputs)
                            output.setSameDiff(sameDiff);
                        func.setSameDiff(sameDiff);
                    }

                    val initialOuts = allFunctions.get(allFunctions.size() - 1).outputVariables();
                    val firstBackward = initialOuts[0];

                    //start with scalar backprop
                    SDVariable initialGrad = sameDiff.var("one-var", Nd4j.scalar(1.0));
                    sameDiff.forwardVarForGrad.put(firstBackward.getVarName(), initialGrad);
                    sameDiff.gradients.put(firstBackward.getVarName(), initialGrad);

                    SDVariable gradientBackwardsMarker = sameDiff.gradientBackwardsMarker(firstBackward);

                    //reinitialize list with all declared variables
                    allFunctions = new ArrayList<DifferentialFunction>(sameDiff.functionInstancesById.values());
                    Collections.reverse(allFunctions);


                    for (DifferentialFunction action : allFunctions) {
                        if (action instanceof GradientBackwardsMarker) {
                            log.warn("Action op state is null for " + action.opName());
                            continue;
                        }

                        DifferentialFunction currFunction = action;
                        Preconditions.checkState(currFunction.getSameDiff() == sameDiff, "Wrong samediff instance found!");
                        //Preconditions.checkNotNull("Gradient for " + currFunction.opName() + " was null ! " + sameDiff.getVariableForVertexId(currFunction.getVertexId()).getGradient());
                        val args = currFunction.outputVariables();
                        for (val arg : args) {
                            if (arg.getSameDiff() != sameDiff) {
                                arg.setSameDiff(sameDiff);
                            }
                        }


                        List<SDVariable> grads = new ArrayList<>();
                        for (val varToGrad : args) {
                            val grad = varToGrad.gradient();
                            if (grad == null)
                                throw new ND4JIllegalStateException("No gradient found for " + varToGrad.getVarName());
                            grads.add(grad);
                        }

                        List<SDVariable> currFnGrads = currFunction.diff(grads);
                    }


                    if (sameDiff.isDebugMode()) {
                        //ensure all gradients are present for all variables
                        for (SDVariable sdVariable : variables()) {
                            sdVariable.gradient();
                        }
                    }


                    return new SDVariable[]{sameDiff.var("grad", new int[]{1, 1})};
                }
            });


        Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> forward = exec("grad");
        SameDiff grad = getFunction("grad");
        if (grad.isDebugMode()) {
            //ensure all gradients are present for all variables
            for (SDVariable sdVariable : grad.variables()) {
                sdVariable.gradient();
            }
        }

        return forward;
    }
public Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> execBackwards() {

        final SameDiff outer = this;
        if (getFunction("grad") == null)
            defineFunction("grad", new SameDiffFunctionDefinition() {

                @Override
                public SDVariable[] define(SameDiff sameDiff, Map<String, INDArray> inputs, SDVariable[] variableInputs) {
                    //propagate graph to this samediff instance
                    //which will also contain the backward
                    if (SameDiff.this.debugMode) {
                        sameDiff.enableDebugMode();
                    }

                    outer.invokeGraphOn(sameDiff);

                    List<DifferentialFunction> allFunctions = new ArrayList<>(sameDiff.functionInstancesById.values());
                    if (allFunctions.isEmpty()) {
                        throw new ND4JIllegalStateException("No ops found!");
                    }


                    for (val func : allFunctions) {
                        if (func instanceof SDVariable) {
                            continue;
                        }

                        val args = func.args();
                        for (val arg : args)
                            arg.setSameDiff(sameDiff);
                        val outputs = func.outputVariables();
                        for (val output : outputs)
                            output.setSameDiff(sameDiff);
                        func.setSameDiff(sameDiff);
                    }

                    val initialOuts = allFunctions.get(allFunctions.size() - 1).outputVariables();
                    val firstBackward = initialOuts[0];

                    //start with scalar backprop
                    SDVariable initialGrad = sameDiff.var("one-var", Nd4j.scalar(1.0));
                    sameDiff.forwardVarForGrad.put(firstBackward.getVarName(), initialGrad);
                    sameDiff.gradients.put(firstBackward.getVarName(), initialGrad);

                    SDVariable gradientBackwardsMarker = sameDiff.gradientBackwardsMarker(firstBackward);

                    //reinitialize list with all declared variables
                    allFunctions = new ArrayList<DifferentialFunction>(sameDiff.functionInstancesById.values());
                    Collections.reverse(allFunctions);


                    for (DifferentialFunction action : allFunctions) {
                        if (action instanceof GradientBackwardsMarker) {
                            log.warn("Action op state is null for " + action.opName());
                            continue;
                        }

                        DifferentialFunction currFunction = action;
                        Preconditions.checkState(currFunction.getSameDiff() == sameDiff, "Wrong samediff instance found!");
                        //Preconditions.checkNotNull("Gradient for " + currFunction.opName() + " was null ! " + sameDiff.getVariableForVertexId(currFunction.getVertexId()).getGradient());
                        val args = currFunction.outputVariables();
                        for (val arg : args) {
                            if (arg.getSameDiff() != sameDiff) {
                                arg.setSameDiff(sameDiff);
                            }
                        }


                        List<SDVariable> grads = new ArrayList<>();
                        for (val varToGrad : args) {
                            val grad = varToGrad.gradient();
                            if (grad == null)
                                throw new ND4JIllegalStateException("No gradient found for " + varToGrad.getVarName());
                            grads.add(grad);
                        }

                        List<SDVariable> currFnGrads = currFunction.diff(grads);
                    }


                    if (sameDiff.isDebugMode()) {
                        //ensure all gradients are present for all variables
                        for (SDVariable sdVariable : variables()) {
                            sdVariable.gradient();
                        }
                    }


                    return new SDVariable[]{sameDiff.var("grad", new int[]{1, 1})};
                }
            });


        Pair<Map<SDVariable, DifferentialFunction>, List<DifferentialFunction>> forward = exec("grad");
        SameDiff grad = getFunction("grad");
        if (grad.isDebugMode()) {
            //ensure all gradients are present for all variables
            for (SDVariable sdVariable : grad.variables()) {
                sdVariable.gradient();
            }
        }

        return forward;
    }
Builds a backwards graph
and executes the operations
on that graph.

@return