Summary
TCP is a software layer which supports full-duplex, but doesn't guarantee it. If the physical hardware layer is only half-duplex Ethernet, then technically you'd be getting time-sliced half-duplex at the hardware layer, even though the TCP software layer wouldn't know the difference.
So, if the hardware supports it, then TCP is truly full duplex. If the hardware is only half-duplex, then the TCP software acts like it is full-duplex because it allows "simultaneous" bi-directional communication, but technically it is only half-duplex.
Refer back to paragraph one above: therefore, TCP is a software layer which supports full-duplex, but doesn't guarantee it.
Ethernet can be half-duplex or full-duplex at the physical hardware layer
Modern Ethernet, however, starting with the 10BASE-T [10 Mbps] standard, apparently, is now truly full-duplex. See here: https://en.wikipedia.org/wiki/Ethernet (emphasis added):
Furthermore, the 10BASE-T [10 Mbps] standard introduced a full duplex mode of operation which became common with Fast Ethernet [100 Mbps] and the de facto standard with Gigabit Ethernet [1000 Mbps]. In full duplex, switch and station can send and receive simultaneously, and therefore modern Ethernets are completely collision-free.
In both cases: whether half-duplex vs full-duplex at the physical hardware layer, TCP is still bidirectional.
To further complicate the matter, apparently all of the Ethernet standards define both full-duplex and half-duplex communication options, but "half-duplex operation for gigabit speed is not supported by any existing hardware." See here: https://en.wikipedia.org/wiki/Ethernet_over_twisted_pair#Autonegotiation_and_duplex (emphasis added):
Autonegotiation and duplex
Ethernet over twisted-pair standards up through Gigabit Ethernet define both full-duplex and half-duplex communication. However, half-duplex operation for gigabit speed is not supported by any existing hardware.[27][28] Higher speed standards, 2.5GBASE-T up to 40GBASE-T[29] running at 2.5 to 40 Gbit/s, consequently define only full-duplex point-to-point links which are generally connected by network switches, and do not support the traditional shared-medium CSMA/CD operation.[30]
Many different modes of operations (10BASE-T half-duplex, 10BASE-T full-duplex, 100BASE-TX half-duplex, etc.) exist for Ethernet over twisted pair, and most network adapters are capable of different modes of operation. Autonegotiation is required in order to make a working 1000BASE-T connection.
More interesting tidbits I just learned
I've always wondered: "what the heck does 'BASE' mean in 10BASE-T, 100BASE-T, etc?"
Answer:
https://en.wikipedia.org/wiki/Classic_Ethernet:
In 10BASE-X, the 10 represents its maximum throughput of 10 Mbit/s, BASE indicates its use of baseband transmission, and X indicates the type of medium used.
And: https://en.wikipedia.org/wiki/Baseband:
A baseband signal or lowpass signal is a signal that can include frequencies that are very near zero, by comparison with its highest frequency (for example, a sound waveform can be considered as a baseband signal, whereas a radio signal or any other modulated signal is not).
So, "BASE" means that it uses a baseband signal, which is defined as a low-pass signal which can go from 0 Hz to cutoff_freq Hz, rather than a frequency-modulated (FM) signal which varies within a certain pass-band (vs baseband) range of x Hz to y Hz, for instance. FM radio is a passband signal, not a baseband signal. Ethernet, apparently, is a baseband signal.
See also: https://en.wikipedia.org/wiki/Passband
T
stands for "twisted", as in the twisted pair cabling used to transmit the signals. See: https://www.techtarget.com/searchnetworking/definition/10BASE-T:
10BASE-T is a shorthand identifier designated by IEEE. The 10 refers to a maximum transmission speed of 10 Mbps. BASE refers to baseband signaling, which means that it can only carry Ethernet signals on the medium. T refers to twisted as in twisted-pair cabling.