code: def to_device(t, device_str):
      """
      This function is a replacement of .to(another_device) such that it allows the
      casting to be traced properly by explicitly calling the underlying copy ops.
      It also avoids introducing unncessary op when casting to the same device.
      """
      src = t.device
      dst = torch.device(device_str)
  
      if src == dst:
          return t
      elif src.type == "cuda" and dst.type == "cpu":
          return torch.ops._caffe2.CopyGPUToCPU(t)
      elif src.type == "cpu" and dst.type == "cuda":
          return torch.ops._caffe2.CopyCPUToGPU(t)
      else:
          raise RuntimeError(
              "Can't cast tensor from device {} to device {}".format(
                  src, dst
              )
          )
  
imports: import collections
  import copy
  import functools
  import logging
  import numpy
  import os
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  from unittest import mock
  import caffe2.python.utils
  import torch
  import torch.nn.functional
  from caffe2.proto import caffe2_pb2
  from caffe2.python import core, net_drawer, workspace
  from torch.nn.functional import interpolate
label_desc: Use image node_id 1 for calling a global function with example usage: to_device(t, device_str) and returns: t, torch, torch