To answer this question we may need to differentiate between TCP, the API-agnostic protocol, and BSD Sockets, the most well-known and widely-adopted API by which apps access the features of their OSes' TCP stacks.
TCP, the protocol, as you've already noted, considers each 4-tuple (src ip, src port, dst ip, dst port) to be a separate connection. Change any one of the items in that 4-tuple and it's a totally separate connection. So, Yes, TCP the protocol can handle multiple connections from a single source IP address and source port.
Whether or not there's an easy way to access that functionality from the venerable BSD Sockets API may be a different question.
TCP doesn't really define what a "request" looks like; as a transport protocol it only provides a duplex data stream (no different from data transfer over a serial port) and leaves it up to the application to work out the rest.
This also means that requests aren't targeted to a port; they're targeted to sent over a specific connection (data stream). Individual TCP packets have no meaning on their own; they're always reassembled to a continuous stream of data. You've already noted that each packet carries destination and source port numbers, identifying it as belonging to a specific connection. (Note: They don't exactly distinguish a specific client, as a single client may open multiple connections; instead they distinguish a specific stream of data.)
So the question really has nothing to do with ports anymore – the only thing left to ask is about how protocols running over TCP distinguish multiple requests over the same connection.
Some protocols aren't even request-oriented to begin with – they might be command-oriented, like FTP or SMTP; or they might have a mix of requests with and without a response, like SSH; or they might transfer unstructured data that arguably doesn't look anything like made out of distinct requests at all, like simple Telnet.
Some protocols, like HTTP/1.0 or Gopher or WHOIS, only allow one request per connection. Once the server has sent the response it just closes the connection, and the client has to connect again (with a new TCP src/dst port pair).
HTTP/1.1 supports long-lived connections, but still only one request at a time. The client has to wait for the first response to finish before sending a second request. (And now there's a need to distinguish multiple responses: for regular resources the HTTP client uses the 'Content-Length' header to know when the response is done, and "indefinite length" responses are sent using a 'chunked' format.)
There is also an HTTP/1.1 extension called "pipelining" that allows multiple requests to be stacked and sent at once. Its mechanism is simple: responses arrive in exactly the same order as requests. (But note that although most HTTP clients use long-lived connections, they do not use HTTP pipelining as it turned out to offer more problems than solutions.)
Some protocols add their own multiplexing on top of the TCP-provided stream. The most well-known example by now is HTTP/2, which has a system of "streams" over a single TCP connection – each request and response is assigned its own stream, divided into small chunks, and the chunks carry their length and the stream ID. The receiver can distinguish multiple requests by reassembling them based on stream ID ... which is practically mirroring how TCP works.
Other protocols like DNS are simpler but have the same general concepts; a DNS request or response over TCP is prefixed with its own length in bytes, so the receiver knows exactly how many bytes the 1st request is, and therefore where the 2nd request starts. Responses again carry a "request ID" and the client can know which response belongs to which request.
So in general, there are two common formats for delimiting multiple requests over a single TCP connection or other transport stream:
Line-based, where each packet is terminated or delimited with a line break or another special character. IRC, FTP (control), SMTP are mostly line-based.
Length-based, where each packet is prefixed with its own length in bytes. SSH, DNS, git://, HTTP/2 are length-based.
HTTP/1.x is an unfortunate mix of both: the request/response header is line-based, but the body is length-based.
There are other weirdos, e.g. IMAP is line-based except when it isn't.
And there are two common methods for processing multiple requests and sorting out the corresponding responses (if the protocol allows that):
Pipelining – the client can submit multiple requests in a specific order, and the responses arrive in exactly the same order.
So in HTTP/1.1, if the client requests page A, page B, page C, then the server responds with page A, page B, and page C always in that order.
Multiplexing – the client can submit multiple requests with individual "request IDs", and the responses may arrive in any order, as each response carries the original "request ID" that prompted it.
For example, in DNS, the client can request google.com/A (req#1234) and facebook.com/AAAA (req#3456), and the server may respond to req#3456 before it ever gets around to handling req#1234.
IMAP has tagged requests/responses, but it also has unsolicited responses that the server may send unrelated to any particular request (e.g. push notifications).
Multiplexing can also be used with "channel IDs", as is the case in HTTP/2 and SSHv2. The difference is that "channel IDs" are long-lived and indeed work much like the ports in TCP header, whereas "request IDs" are short-lived.
In HTTP/2, each request is assigned a stream and the responses may be interleaved – the client may receive some data tagged "stream A", some data tagged "stream B", and then more data for stream A. Although streams only carry a single request/response, they're still made out of multiple different messages and so act more like channel IDs.
There may even be a mix of both – e.g. a protocol may have multiplexed channels, but over each channel it may carry multiple tagged or pipelined requests.
SSHv2 works like that – the same connection may have multiple interactive shell channels (unstructured), SFTP channels (pipelined request/response), TCP forwarding channels (unstructured), an ssh-agent forwarding channel (pipelined request/response), and so on.
Best Answer
TCP and HTTP are different things.
TCP is the transport layer. By definition, it's responsible for carrying application layer protocols (HTTP in your case) over it. TCP does not run over a port. It is the arbitrator of ports. In other words, when you connect to an HTTP server, you connect on TCP port 80. When you connect to HTTPS, you're connecting over TCP port 443.
HTTP and HTTPS can run over any TCP port. 80 and 443 are just the common ones. You can make any application listen on those ports if you want. So yes, you can connect to your server over port 80 using some other protocol instead of HTTP, but only if the server is configured to listen on that port using that other protocol, and only if HTTP or HTTPS are configured to not use those ports (assuming you're running a web server on it).
Now, you mentioned that your provider is making use of a proxy. Can you make a non-HTTP/HTTPS connection over port 80 or 443? That depends on how smart the proxy is. If it's performing packet inspection, it could be verifying the HTTP headers to make sure that the traffic going over those ports is indeed HTTP traffic. There are ways to fake it, but it depends on how deeply the proxy is inspecting the traffic. If the proxy is blocking non-HTTP/HTTPS traffic on HTTP/HTTPS ports, then there isn't much you can do about it except squawk at your provider (or pay the higher price as the case may be).
When it comes to how various mobile applications communicate, it all depends on how the vendor wrote them. Most use HTTP or HTTPS over port 80 or 443 respectively because most mobile apps are just skinned web apps. But there's no rule that says they have to, and there's no real way for you to know unless you sniff the packets somehow.
I hope I have answered your question.