constructor(graph, parent){
        this.graph = graph;
        this.parent = parent;
        this.compiledMap = new Map();
        this.parseNodeNameCache = new Map();
        this._weightMap = {};
        this.SEPARATOR = ",";
        this._functions = {};
        this._functionExecutorMap = {};
        this.keepIntermediateTensors = false;
        this._outputs = graph.outputs;
        this._inputs = graph.inputs;
        this._initNodes = graph.initNodes;
        this._signature = graph.signature;
        this._functions = graph.functions;
        // create sub-graph executors
        if (graph.functions != null) Object.keys(graph.functions).forEach((name)=>{
            this._functionExecutorMap[name] = new GraphExecutor(graph.functions[name], this);
        });
    }
@param graph Graph the model or function graph to be executed.
@param parent When building function exector you need to set the parent
executor. Since the weights and function executor maps are set at parant
level, that function executor can access the function maps and weight maps
through the parent.