We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SVD is returning 4 pointers instead of 3
## Description
When sending a tensor to a worker and performing SVD, returns four pointers instead of three. Also, the third one is not gettable. By experimentation, I have had to solve the issue using `U, s, _, V = x.svd()`.

## How to Reproduce
```python
import torch
import syft as sy

hook = sy.TorchHook(torch)
bob = sy.VirtualWorker(hook, id='bob')

x = torch.rand(250, 84).send(bob)  # Synthetic tensor
x.svd()

# Output:
# ((Wrapper)>[PointerTensor | me:88822589827 -> bob:10423896311],
#  (Wrapper)>[PointerTensor | me:22528885369 -> bob:34285527022],
#  (Wrapper)>[PointerTensor | me:46709676193 -> bob:67244907535],
#  (Wrapper)>[PointerTensor | me:235847656 -> bob:15738446586])
```

## Expected Behavior
Should return **three** pointers: `U, s, V = x.svd()`

## System Information
 - Official released Docker container
 - Same for pip package:
   - Ubuntu 18.04.5 LTS (Bionic Beaver)
   - Python 3.6.9

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `syft/generic/object_storage.py`
Content:
```
1 from collections import defaultdict
2 from typing import Union
3 
4 from syft.exceptions import ObjectNotFoundError
5 from syft.generic.frameworks.types import FrameworkTensor
6 from syft.generic.frameworks.types import FrameworkTensorType
7 from syft.generic.abstract.tensor import AbstractTensor
8 from syft.workers.abstract import AbstractWorker
9 
10 
11 class ObjectStore:
12     """A storage of objects identifiable by their id.
13 
14     A wrapper object to a collection of objects where all objects
15     are stored using their IDs as keys.
16     """
17 
18     def __init__(self, owner: AbstractWorker = None):
19         self.owner = owner
20 
21         # This is the collection of objects being stored.
22         self._objects = {}
23         # This is an index to retrieve objects from their tags in an efficient way
24         self._tag_to_object_ids = defaultdict(set)
25 
26         # Garbage collect all remote data on a worker every garbage_delay seconds
27         self.garbage_delay = 0
28         # Store at most trash_capacity elements before garbage collecting
29         self.trash_capacity = 10_000
30         # Trash is a dict referencing for each worker key a tuple with the timestamp
31         # of the last GC and the list of object to GC
32         self.trash = {}
33 
34     @property
35     def _tensors(self):
36         return {id_: obj for id_, obj in self._objects.items() if isinstance(obj, FrameworkTensor)}
37 
38     def register_obj(self, obj: object, obj_id: Union[str, int] = None):
39         """Registers the specified object with the current worker node.
40 
41         Selects an id for the object, assigns a list of owners, and establishes
42         whether it's a pointer or not. This method is generally not used by the
43         client and is instead used by internal processes (hooks and workers).
44 
45         Args:
46             obj: A torch Tensor or Variable object to be registered.
47             obj_id (int or string): random integer between 0 and 1e10 or
48             string uniquely identifying the object.
49         """
50         if obj_id is not None and hasattr(obj, "id"):
51             obj.id = obj_id
52         self.set_obj(obj)
53 
54     def de_register_obj(self, obj: object, _recurse_torch_objs: bool = True):
55         """Deregisters the specified object.
56 
57         Deregister and remove attributes which are indicative of registration.
58 
59         Args:
60             obj: A torch Tensor or Variable object to be deregistered.
61             _recurse_torch_objs: A boolean indicating whether the object is
62                 more complex and needs to be explored. Is not supported at the
63                 moment.
64         """
65         if hasattr(obj, "id"):
66             self.rm_obj(obj.id)
67         if hasattr(obj, "_owner"):
68             del obj._owner
69 
70     def get_obj(self, obj_id: Union[str, int]) -> object:
71         """Returns the object from registry.
72 
73         Look up an object from the registry using its ID.
74 
75         Args:
76             obj_id: A string or integer id of an object to look up.
77 
78         Returns:
79             Object with id equals to `obj_id`.
80         """
81 
82         try:
83             obj = self._objects[obj_id]
84         except KeyError as e:
85             if obj_id not in self._objects:
86                 raise ObjectNotFoundError(obj_id, self)
87             else:
88                 raise e
89 
90         return obj
91 
92     def set_obj(self, obj: Union[FrameworkTensorType, AbstractTensor]) -> None:
93         """Adds an object to the registry of objects.
94 
95         Args:
96             obj: A torch or syft tensor with an id.
97         """
98         obj.owner = self.owner
99         self._objects[obj.id] = obj
100         # Add entry in the tag index
101         if obj.tags:
102             for tag in obj.tags:
103                 if tag not in self._tag_to_object_ids:
104                     self._tag_to_object_ids[tag] = {obj.id}
105                 else:
106                     self._tag_to_object_ids[tag].add(obj.id)
107 
108     def rm_obj(self, obj_id: Union[str, int], force=False):
109         """Removes an object.
110 
111         Remove the object from the permanent object registry if it exists.
112 
113         Args:
114             obj_id: A string or integer representing id of the object to be
115                 removed.
116             force: if true, explicitly forces removal of the object modifying the
117                 `garbage_collect_data` attribute.
118         """
119         if obj_id in self._objects:
120             obj = self._objects[obj_id]
121             # update tag index
122             if obj.tags:
123                 for tag in obj.tags:
124                     if tag not in self._tag_to_object_ids:
125                         self._tag_to_object_ids[tag].remove(obj.id)
126 
127             if force and hasattr(obj, "child") and hasattr(obj.child, "garbage_collect_data"):
128                 obj.child.garbage_collect_data = True
129 
130             del self._objects[obj_id]
131 
132     def force_rm_obj(self, obj_id: Union[str, int]):
133         self.rm_obj(obj_id, force=True)
134 
135     def clear_objects(self):
136         """Removes all objects from the object storage."""
137         self._objects.clear()
138 
139     def current_objects(self):
140         """Returns a copy of the objects in the object storage."""
141         return self._objects.copy()
142 
143     def find_by_id(self, id):
144         """Local search by id"""
145         return self._objects.get(id)
146 
147     def find_by_tag(self, tag):
148         """Local search by tag
149 
150         Args:
151             tag (str): exact tag searched
152 
153         Return:
154             A list of results, possibly empty
155         """
156         if tag in self._tag_to_object_ids:
157             results = []
158             for obj_id in self._tag_to_object_ids[tag]:
159                 obj = self.find_by_id(obj_id)
160                 if obj is not None:
161                     results.append(obj)
162             return results
163         return []
164 
165     def register_tags(self, obj):
166         # NOTE: this is a fix to correct faulty registration that can sometimes happen
167         if obj.id not in self._objects:
168             self.owner.register_obj(obj)
169 
170         for tag in obj.tags:
171             self._tag_to_object_ids[tag].add(obj.id)
172 
173     def __len__(self):
174         """
175         Return the number of objects in the store
176         """
177         return len(self._objects)
178 
179     def __str__(self):
180         return f"<ObjectStorage of {self.owner.id}>"
181
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/syft/generic/object_storage.py b/syft/generic/object_storage.py
--- a/syft/generic/object_storage.py
+++ b/syft/generic/object_storage.py
@@ -6,6 +6,7 @@
 from syft.generic.frameworks.types import FrameworkTensorType
 from syft.generic.abstract.tensor import AbstractTensor
 from syft.workers.abstract import AbstractWorker
+import torch
 
 
 class ObjectStore:
@@ -62,7 +63,8 @@
                 more complex and needs to be explored. Is not supported at the
                 moment.
         """
-        if hasattr(obj, "id"):
+        has_id = hasattr(obj, "_id") if isinstance(obj, torch.Tensor) else hasattr(obj, "id")
+        if has_id:
             self.rm_obj(obj.id)
         if hasattr(obj, "_owner"):
             del obj._owner

{"golden_diff": "diff --git a/syft/generic/object_storage.py b/syft/generic/object_storage.py\n--- a/syft/generic/object_storage.py\n+++ b/syft/generic/object_storage.py\n@@ -6,6 +6,7 @@\n from syft.generic.frameworks.types import FrameworkTensorType\n from syft.generic.abstract.tensor import AbstractTensor\n from syft.workers.abstract import AbstractWorker\n+import torch\n \n \n class ObjectStore:\n@@ -62,7 +63,8 @@\n                 more complex and needs to be explored. Is not supported at the\n                 moment.\n         \"\"\"\n-        if hasattr(obj, \"id\"):\n+        has_id = hasattr(obj, \"_id\") if isinstance(obj, torch.Tensor) else hasattr(obj, \"id\")\n+        if has_id:\n             self.rm_obj(obj.id)\n         if hasattr(obj, \"_owner\"):\n             del obj._owner\n", "issue": "SVD is returning 4 pointers instead of 3\n## Description\r\nWhen sending a tensor to a worker and performing SVD, returns four pointers instead of three. Also, the third one is not gettable. By experimentation, I have had to solve the issue using `U, s, _, V = x.svd()`.\r\n\r\n## How to Reproduce\r\n```python\r\nimport torch\r\nimport syft as sy\r\n\r\nhook = sy.TorchHook(torch)\r\nbob = sy.VirtualWorker(hook, id='bob')\r\n\r\nx = torch.rand(250, 84).send(bob)  # Synthetic tensor\r\nx.svd()\r\n\r\n# Output:\r\n# ((Wrapper)>[PointerTensor | me:88822589827 -> bob:10423896311],\r\n#  (Wrapper)>[PointerTensor | me:22528885369 -> bob:34285527022],\r\n#  (Wrapper)>[PointerTensor | me:46709676193 -> bob:67244907535],\r\n#  (Wrapper)>[PointerTensor | me:235847656 -> bob:15738446586])\r\n```\r\n\r\n## Expected Behavior\r\nShould return **three** pointers: `U, s, V = x.svd()`\r\n\r\n## System Information\r\n - Official released Docker container\r\n - Same for pip package:\r\n   - Ubuntu 18.04.5 LTS (Bionic Beaver)\r\n   - Python 3.6.9\n", "before_files": [{"content": "from collections import defaultdict\nfrom typing import Union\n\nfrom syft.exceptions import ObjectNotFoundError\nfrom syft.generic.frameworks.types import FrameworkTensor\nfrom syft.generic.frameworks.types import FrameworkTensorType\nfrom syft.generic.abstract.tensor import AbstractTensor\nfrom syft.workers.abstract import AbstractWorker\n\n\nclass ObjectStore:\n    \"\"\"A storage of objects identifiable by their id.\n\n    A wrapper object to a collection of objects where all objects\n    are stored using their IDs as keys.\n    \"\"\"\n\n    def __init__(self, owner: AbstractWorker = None):\n        self.owner = owner\n\n        # This is the collection of objects being stored.\n        self._objects = {}\n        # This is an index to retrieve objects from their tags in an efficient way\n        self._tag_to_object_ids = defaultdict(set)\n\n        # Garbage collect all remote data on a worker every garbage_delay seconds\n        self.garbage_delay = 0\n        # Store at most trash_capacity elements before garbage collecting\n        self.trash_capacity = 10_000\n        # Trash is a dict referencing for each worker key a tuple with the timestamp\n        # of the last GC and the list of object to GC\n        self.trash = {}\n\n    @property\n    def _tensors(self):\n        return {id_: obj for id_, obj in self._objects.items() if isinstance(obj, FrameworkTensor)}\n\n    def register_obj(self, obj: object, obj_id: Union[str, int] = None):\n        \"\"\"Registers the specified object with the current worker node.\n\n        Selects an id for the object, assigns a list of owners, and establishes\n        whether it's a pointer or not. This method is generally not used by the\n        client and is instead used by internal processes (hooks and workers).\n\n        Args:\n            obj: A torch Tensor or Variable object to be registered.\n            obj_id (int or string): random integer between 0 and 1e10 or\n            string uniquely identifying the object.\n        \"\"\"\n        if obj_id is not None and hasattr(obj, \"id\"):\n            obj.id = obj_id\n        self.set_obj(obj)\n\n    def de_register_obj(self, obj: object, _recurse_torch_objs: bool = True):\n        \"\"\"Deregisters the specified object.\n\n        Deregister and remove attributes which are indicative of registration.\n\n        Args:\n            obj: A torch Tensor or Variable object to be deregistered.\n            _recurse_torch_objs: A boolean indicating whether the object is\n                more complex and needs to be explored. Is not supported at the\n                moment.\n        \"\"\"\n        if hasattr(obj, \"id\"):\n            self.rm_obj(obj.id)\n        if hasattr(obj, \"_owner\"):\n            del obj._owner\n\n    def get_obj(self, obj_id: Union[str, int]) -> object:\n        \"\"\"Returns the object from registry.\n\n        Look up an object from the registry using its ID.\n\n        Args:\n            obj_id: A string or integer id of an object to look up.\n\n        Returns:\n            Object with id equals to `obj_id`.\n        \"\"\"\n\n        try:\n            obj = self._objects[obj_id]\n        except KeyError as e:\n            if obj_id not in self._objects:\n                raise ObjectNotFoundError(obj_id, self)\n            else:\n                raise e\n\n        return obj\n\n    def set_obj(self, obj: Union[FrameworkTensorType, AbstractTensor]) -> None:\n        \"\"\"Adds an object to the registry of objects.\n\n        Args:\n            obj: A torch or syft tensor with an id.\n        \"\"\"\n        obj.owner = self.owner\n        self._objects[obj.id] = obj\n        # Add entry in the tag index\n        if obj.tags:\n            for tag in obj.tags:\n                if tag not in self._tag_to_object_ids:\n                    self._tag_to_object_ids[tag] = {obj.id}\n                else:\n                    self._tag_to_object_ids[tag].add(obj.id)\n\n    def rm_obj(self, obj_id: Union[str, int], force=False):\n        \"\"\"Removes an object.\n\n        Remove the object from the permanent object registry if it exists.\n\n        Args:\n            obj_id: A string or integer representing id of the object to be\n                removed.\n            force: if true, explicitly forces removal of the object modifying the\n                `garbage_collect_data` attribute.\n        \"\"\"\n        if obj_id in self._objects:\n            obj = self._objects[obj_id]\n            # update tag index\n            if obj.tags:\n                for tag in obj.tags:\n                    if tag not in self._tag_to_object_ids:\n                        self._tag_to_object_ids[tag].remove(obj.id)\n\n            if force and hasattr(obj, \"child\") and hasattr(obj.child, \"garbage_collect_data\"):\n                obj.child.garbage_collect_data = True\n\n            del self._objects[obj_id]\n\n    def force_rm_obj(self, obj_id: Union[str, int]):\n        self.rm_obj(obj_id, force=True)\n\n    def clear_objects(self):\n        \"\"\"Removes all objects from the object storage.\"\"\"\n        self._objects.clear()\n\n    def current_objects(self):\n        \"\"\"Returns a copy of the objects in the object storage.\"\"\"\n        return self._objects.copy()\n\n    def find_by_id(self, id):\n        \"\"\"Local search by id\"\"\"\n        return self._objects.get(id)\n\n    def find_by_tag(self, tag):\n        \"\"\"Local search by tag\n\n        Args:\n            tag (str): exact tag searched\n\n        Return:\n            A list of results, possibly empty\n        \"\"\"\n        if tag in self._tag_to_object_ids:\n            results = []\n            for obj_id in self._tag_to_object_ids[tag]:\n                obj = self.find_by_id(obj_id)\n                if obj is not None:\n                    results.append(obj)\n            return results\n        return []\n\n    def register_tags(self, obj):\n        # NOTE: this is a fix to correct faulty registration that can sometimes happen\n        if obj.id not in self._objects:\n            self.owner.register_obj(obj)\n\n        for tag in obj.tags:\n            self._tag_to_object_ids[tag].add(obj.id)\n\n    def __len__(self):\n        \"\"\"\n        Return the number of objects in the store\n        \"\"\"\n        return len(self._objects)\n\n    def __str__(self):\n        return f\"<ObjectStorage of {self.owner.id}>\"\n", "path": "syft/generic/object_storage.py"}], "after_files": [{"content": "from collections import defaultdict\nfrom typing import Union\n\nfrom syft.exceptions import ObjectNotFoundError\nfrom syft.generic.frameworks.types import FrameworkTensor\nfrom syft.generic.frameworks.types import FrameworkTensorType\nfrom syft.generic.abstract.tensor import AbstractTensor\nfrom syft.workers.abstract import AbstractWorker\nimport torch\n\n\nclass ObjectStore:\n    \"\"\"A storage of objects identifiable by their id.\n\n    A wrapper object to a collection of objects where all objects\n    are stored using their IDs as keys.\n    \"\"\"\n\n    def __init__(self, owner: AbstractWorker = None):\n        self.owner = owner\n\n        # This is the collection of objects being stored.\n        self._objects = {}\n        # This is an index to retrieve objects from their tags in an efficient way\n        self._tag_to_object_ids = defaultdict(set)\n\n        # Garbage collect all remote data on a worker every garbage_delay seconds\n        self.garbage_delay = 0\n        # Store at most trash_capacity elements before garbage collecting\n        self.trash_capacity = 10_000\n        # Trash is a dict referencing for each worker key a tuple with the timestamp\n        # of the last GC and the list of object to GC\n        self.trash = {}\n\n    @property\n    def _tensors(self):\n        return {id_: obj for id_, obj in self._objects.items() if isinstance(obj, FrameworkTensor)}\n\n    def register_obj(self, obj: object, obj_id: Union[str, int] = None):\n        \"\"\"Registers the specified object with the current worker node.\n\n        Selects an id for the object, assigns a list of owners, and establishes\n        whether it's a pointer or not. This method is generally not used by the\n        client and is instead used by internal processes (hooks and workers).\n\n        Args:\n            obj: A torch Tensor or Variable object to be registered.\n            obj_id (int or string): random integer between 0 and 1e10 or\n            string uniquely identifying the object.\n        \"\"\"\n        if obj_id is not None and hasattr(obj, \"id\"):\n            obj.id = obj_id\n        self.set_obj(obj)\n\n    def de_register_obj(self, obj: object, _recurse_torch_objs: bool = True):\n        \"\"\"Deregisters the specified object.\n\n        Deregister and remove attributes which are indicative of registration.\n\n        Args:\n            obj: A torch Tensor or Variable object to be deregistered.\n            _recurse_torch_objs: A boolean indicating whether the object is\n                more complex and needs to be explored. Is not supported at the\n                moment.\n        \"\"\"\n        has_id = hasattr(obj, \"_id\") if isinstance(obj, torch.Tensor) else hasattr(obj, \"id\")\n        if has_id:\n            self.rm_obj(obj.id)\n        if hasattr(obj, \"_owner\"):\n            del obj._owner\n\n    def get_obj(self, obj_id: Union[str, int]) -> object:\n        \"\"\"Returns the object from registry.\n\n        Look up an object from the registry using its ID.\n\n        Args:\n            obj_id: A string or integer id of an object to look up.\n\n        Returns:\n            Object with id equals to `obj_id`.\n        \"\"\"\n\n        try:\n            obj = self._objects[obj_id]\n        except KeyError as e:\n            if obj_id not in self._objects:\n                raise ObjectNotFoundError(obj_id, self)\n            else:\n                raise e\n\n        return obj\n\n    def set_obj(self, obj: Union[FrameworkTensorType, AbstractTensor]) -> None:\n        \"\"\"Adds an object to the registry of objects.\n\n        Args:\n            obj: A torch or syft tensor with an id.\n        \"\"\"\n        obj.owner = self.owner\n        self._objects[obj.id] = obj\n        # Add entry in the tag index\n        if obj.tags:\n            for tag in obj.tags:\n                if tag not in self._tag_to_object_ids:\n                    self._tag_to_object_ids[tag] = {obj.id}\n                else:\n                    self._tag_to_object_ids[tag].add(obj.id)\n\n    def rm_obj(self, obj_id: Union[str, int], force=False):\n        \"\"\"Removes an object.\n\n        Remove the object from the permanent object registry if it exists.\n\n        Args:\n            obj_id: A string or integer representing id of the object to be\n                removed.\n            force: if true, explicitly forces removal of the object modifying the\n                `garbage_collect_data` attribute.\n        \"\"\"\n        if obj_id in self._objects:\n            obj = self._objects[obj_id]\n            # update tag index\n            if obj.tags:\n                for tag in obj.tags:\n                    if tag not in self._tag_to_object_ids:\n                        self._tag_to_object_ids[tag].remove(obj.id)\n\n            if force and hasattr(obj, \"child\") and hasattr(obj.child, \"garbage_collect_data\"):\n                obj.child.garbage_collect_data = True\n\n            del self._objects[obj_id]\n\n    def force_rm_obj(self, obj_id: Union[str, int]):\n        self.rm_obj(obj_id, force=True)\n\n    def clear_objects(self):\n        \"\"\"Removes all objects from the object storage.\"\"\"\n        self._objects.clear()\n\n    def current_objects(self):\n        \"\"\"Returns a copy of the objects in the object storage.\"\"\"\n        return self._objects.copy()\n\n    def find_by_id(self, id):\n        \"\"\"Local search by id\"\"\"\n        return self._objects.get(id)\n\n    def find_by_tag(self, tag):\n        \"\"\"Local search by tag\n\n        Args:\n            tag (str): exact tag searched\n\n        Return:\n            A list of results, possibly empty\n        \"\"\"\n        if tag in self._tag_to_object_ids:\n            results = []\n            for obj_id in self._tag_to_object_ids[tag]:\n                obj = self.find_by_id(obj_id)\n                if obj is not None:\n                    results.append(obj)\n            return results\n        return []\n\n    def register_tags(self, obj):\n        # NOTE: this is a fix to correct faulty registration that can sometimes happen\n        if obj.id not in self._objects:\n            self.owner.register_obj(obj)\n\n        for tag in obj.tags:\n            self._tag_to_object_ids[tag].add(obj.id)\n\n    def __len__(self):\n        \"\"\"\n        Return the number of objects in the store\n        \"\"\"\n        return len(self._objects)\n\n    def __str__(self):\n        return f\"<ObjectStorage of {self.owner.id}>\"\n", "path": "syft/generic/object_storage.py"}]}