code: def prune_unused_nodes(meta_graph, signature_def):
    
    # Instantiate a temporary empty graph so that we have access to Graph API
    # and import the meta_graph.
    graph = tf_v1.Graph()
    with graph.as_default():
      tf_v1.train.import_meta_graph(meta_graph, input_map={}, import_scope="")
      # Traverse from all outputs and mark all nodes.
      used_node_names = set()
      for _, tensor_def in signature_def.outputs.items():
        output_tensor = graph.get_tensor_by_name(tensor_def.name)
        mark_backward(output_tensor, used_node_names)
      # Filter out all nodes in the meta_graph that are not used.
      node_filter_in_list = []
      for node in meta_graph.graph_def.node:
        # Make a special exception for VarHandleOp. Removing VarhandleOps
        # will make the graph not importable as they often leave nodes hanging.
        # These will be disconnected through the feedmap when importing the
        # metagraph.
        if node.name in used_node_names or node.op == "VarHandleOp":
          node_filter_in_list.append(node)
      del meta_graph.graph_def.node[:]
      meta_graph.graph_def.node.extend(node_filter_in_list)
    del graph
docs: Function to prune unused ops given a signature def.
  
    This function does a graph traversal through from all outputs as
    defined in the signature_def to collect all used nodes. Then, any
    nodes which are unused can be discarded. This is useful for graph which are
    executing eagerly or on TPUs.
  
    Args:
      meta_graph: The input/output MetaGraphDef for which we wish to prune.
     signature_def: A SignatureDef which specifies the outputs from which we wish
       to start graph traversal.