Repository: pandas-dev/pandas

Issue:
BUG: Transpose changes dtype from object to timedelta/datetime
### Pandas version checks

- [X] I have checked that this issue has not already been reported.

- [X] I have confirmed this bug exists on the [latest version](https://pandas.pydata.org/docs/whatsnew/index.html) of pandas.

- [X] I have confirmed this bug exists on the [main branch](https://pandas.pydata.org/docs/dev/getting_started/install.html#installing-the-development-version-of-pandas) of pandas.


### Reproducible Example

```python
df = DataFrame({"a": [pd.Timedelta("1 days"), pd.NaT, pd.Timedelta("2 days")]}, dtype=object)
df.T.dtypes


0    timedelta64[ns]
1     datetime64[ns]
2    timedelta64[ns]
dtype: object
```


### Issue Description

I'd expected this to return object, but this was changed in #26285

### Expected Behavior

The whatsnew looks like the fix was tailored to avoid raising an error, any other motivations?

### Installed Versions

<details>

Replace this line with the output of pd.show_versions()

</details>



Discussion:
I'd expect object too

Patch:
diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst
index 12d35288d1ee6..9000b3fc446c5 100644
--- a/doc/source/whatsnew/v2.1.0.rst
+++ b/doc/source/whatsnew/v2.1.0.rst
@@ -195,7 +195,7 @@ Groupby/resample/rolling
 
 Reshaping
 ^^^^^^^^^
--
+- Bug in :meth:`DataFrame.transpose` inferring dtype for object column (:issue:`51546`)
 -
 
 Sparse
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
index 8cd0ffadcc17c..de4e7deb8d2a9 100644
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -3575,7 +3575,11 @@ def transpose(self, *args, copy: bool = False) -> DataFrame:
                 new_vals = new_vals.copy()
 
             result = self._constructor(
-                new_vals, index=self.columns, columns=self.index, copy=False
+                new_vals,
+                index=self.columns,
+                columns=self.index,
+                copy=False,
+                dtype=new_vals.dtype,
             )
             if using_copy_on_write() and len(self) > 0:
                 result._mgr.add_references(self._mgr)  # type: ignore[arg-type]
@@ -3597,7 +3601,9 @@ def transpose(self, *args, copy: bool = False) -> DataFrame:
             new_arr = self.values.T
             if copy:
                 new_arr = new_arr.copy()
-            result = self._constructor(new_arr, index=self.columns, columns=self.index)
+            result = self._constructor(
+                new_arr, index=self.columns, columns=self.index, dtype=new_arr.dtype
+            )
 
         return result.__finalize__(self, method="transpose")
 


Test patch:
diff --git a/pandas/tests/frame/methods/test_transpose.py b/pandas/tests/frame/methods/test_transpose.py
index 6213a6dbbd0ca..e8710cea95219 100644
--- a/pandas/tests/frame/methods/test_transpose.py
+++ b/pandas/tests/frame/methods/test_transpose.py
@@ -7,6 +7,8 @@
     DataFrame,
     DatetimeIndex,
     IntervalIndex,
+    Series,
+    Timestamp,
     date_range,
     timedelta_range,
 )
@@ -63,7 +65,7 @@ def test_transpose_tzaware_2col_mixed_tz(self):
         df4 = DataFrame({"A": dti, "B": dti2})
         assert (df4.dtypes == [dti.dtype, dti2.dtype]).all()
         assert (df4.T.dtypes == object).all()
-        tm.assert_frame_equal(df4.T.T, df4)
+        tm.assert_frame_equal(df4.T.T, df4.astype(object))
 
     @pytest.mark.parametrize("tz", [None, "America/New_York"])
     def test_transpose_preserves_dtindex_equality_with_dst(self, tz):
@@ -83,7 +85,7 @@ def test_transpose_object_to_tzaware_mixed_tz(self):
         df2 = DataFrame([dti, dti2])
         assert (df2.dtypes == object).all()
         res2 = df2.T
-        assert (res2.dtypes == [dti.dtype, dti2.dtype]).all()
+        assert (res2.dtypes == object).all()
 
     def test_transpose_uint64(self, uint64_frame):
         result = uint64_frame.T
@@ -128,3 +130,42 @@ def test_transpose_get_view_dt64tzget_view(self):
 
         rtrip = result._mgr.blocks[0].values
         assert np.shares_memory(arr._ndarray, rtrip._ndarray)
+
+    def test_transpose_not_inferring_dt(self):
+        # GH#51546
+        df = DataFrame(
+            {
+                "a": [Timestamp("2019-12-31"), Timestamp("2019-12-31")],
+            },
+            dtype=object,
+        )
+        result = df.T
+        expected = DataFrame(
+            [[Timestamp("2019-12-31"), Timestamp("2019-12-31")]],
+            columns=[0, 1],
+            index=["a"],
+            dtype=object,
+        )
+        tm.assert_frame_equal(result, expected)
+
+    def test_transpose_not_inferring_dt_mixed_blocks(self):
+        # GH#51546
+        df = DataFrame(
+            {
+                "a": Series(
+                    [Timestamp("2019-12-31"), Timestamp("2019-12-31")], dtype=object
+                ),
+                "b": [Timestamp("2019-12-31"), Timestamp("2019-12-31")],
+            }
+        )
+        result = df.T
+        expected = DataFrame(
+            [
+                [Timestamp("2019-12-31"), Timestamp("2019-12-31")],
+                [Timestamp("2019-12-31"), Timestamp("2019-12-31")],
+            ],
+            columns=[0, 1],
+            index=["a", "b"],
+            dtype=object,
+        )
+        tm.assert_frame_equal(result, expected)
diff --git a/pandas/tests/groupby/test_quantile.py b/pandas/tests/groupby/test_quantile.py
index bc0422d41e74a..5801223c0e718 100644
--- a/pandas/tests/groupby/test_quantile.py
+++ b/pandas/tests/groupby/test_quantile.py
@@ -467,7 +467,7 @@ def test_groupby_quantile_dt64tz_period():
 
     # Check that we match the group-by-group result
     exp = {i: df.iloc[i::5].quantile(0.5) for i in range(5)}
-    expected = DataFrame(exp).T
+    expected = DataFrame(exp).T.infer_objects()
     expected.index = expected.index.astype(np.int_)
 
     tm.assert_frame_equal(result, expected)