class_docstr: Generates model graph, each node is created from single or multiple jit trace nodes.
class_docstr_tok: ["Generates","model","graph",",","each","node","is","created","from","single","or","multiple","jit","trace","nodes","."]
docstr: Unpack the tensor tuple or tensor list manually,
  and remove the ListUnpack/TupleUnpack node from
  the graph. Note: this function will change the
  graph structure.
docstr_tok: ["Unpack","the","tensor","tuple","or","tensor","list","manually",",","and","remove","the","ListUnpack\/TupleUnpack","node","from","the","graph",".","Note",":","this","function","will","change","the","graph","structure","."]
code: def unpack_manually(self):
      """
      Unpack the tensor tuple or tensor list manually,
      and remove the ListUnpack/TupleUnpack node from
      the graph. Note: this function will change the
      graph structure.
      """
      if hasattr(self, "unpacked"):
          # if already unpacked the tuple/list manually
          return
      for node in self.nodes_py.nodes_op:
          if node.op_type in [TUPLE_UNPACK_KIND, LIST_UNPACK_KIND]:
              unpack_cpp = node.key_node
              last_cpp = list(unpack_cpp.inputs())[0].node()
              if last_cpp.kind() in [
                  TUPLE_CONSTRUCT_KIND,
                  LIST_CONSTRUCT_KIND,
              ]:
                  # we need check if the tensor tuple or tensor list is produced
                  # by a list/tuple construct node. If so, we can unpack the tuple
                  # or list manunally.
                  _logger.debug(
                      "List/Tuple Construct Node(cpp) %s", str(last_cpp)
                  )
                  _logger.debug(
                      "List/Tuple Unpack Node(cpp) %s", str(unpack_cpp)
                  )
                  assert len(list(unpack_cpp.outputs())) == len(
                      list(last_cpp.inputs())
                  )
                  errmsg = (
                      "%s Input number: %d if inconsistent with the output number %d"
                      % (
                          unpack_cpp,
                          len(node.inputs),
                          len(list(last_cpp.inputs())),
                      )
                  )
  
                  assert len(node.inputs) == len(
                      list(last_cpp.inputs())
                  ), errmsg
                  for _debug_input, _debug_output in zip(
                      node.inputs, node.outputs
                  ):
                      if (
                          _debug_input in self.input_to_node
                          and _debug_output in self.input_to_node
                      ):
                          # input_to_node[_debug_input] is a list of NodePyGroup, because
                          # one tensor can be used as input for multiple nodes at the same time.
  
                          # note that, in this case, the construct cpp node and unpack cpp node
                          # will be merged into the same NodePyGroup, so we remove the `node` from
                          # input_to_node[_debug_input] and directly connect this tensor to the
                          # input_to_node[_debug_output]
                          if node in self.input_to_node[_debug_input]:
                              self.input_to_node[_debug_input].remove(
                                  node
                              )
                          # add the following nodes of _output into the input_to_node[_debug_input]
                          self.input_to_node[_debug_input].extend(
                              self.input_to_node[_debug_output]
                          )
                      # just remove the _debug_output from the grapgh index. So that we can also skip
                      # the construct and tuple
                      if _debug_output in self.input_to_node:
                          for following_node in self.input_to_node[
                              _debug_output
                          ]:
                              _tmp_index = following_node.inputs.index(
                                  _debug_output
                              )
                              following_node.inputs[
                                  _tmp_index
                              ] = _debug_input
  
      self.unpacked = True
  
imports: import logging
  import queue
  import re
  from collections import defaultdict
  from typing import List, Dict
  import torch
  from torch.utils.tensorboard._pytorch_graph import NodePy, NodePyIO, NodePyOP, GraphPy
label_desc: Use image node_id 11 for calling the TorchModuleGraph obj's underlying member method code with example usage: obj.unpack_manually() without return types