Change:
either as a complete Message in the underlying protocol, or in multiple parts. <ins> Messages themselves generally consist of bytes passed in the messageData parameter intended to be processed at an application layer.  However, Message objects presented through the API can carry associated Message Properties passed through the messageContext parameter.  When these are Protocol Specific Properties, they can include metadata that exists separately from a byte encoding.  For example, these Properties can include name-value pairs of information, like HTTP header fields.  In such cases, Messages might be "empty", insofar as they contain zero bytes in the messageData parameter, but can still include data in the messageContext that is interpreted by the Protocol Stack. </ins> 5.1. The effect of the application sending a Message is determined by the

Discussion:
NAME I think I disagree that this needs an API change, but rather a note that a messageData object can be empty. At least in the data objects we work with, they can support 0-length data blobs.
NAME I agree, you're right, this is better.
Is the content of messages always bytes? I certainly got that impression, but didn't see it explicitly either. (The "protocols that expose byte-streams" have that property visible in their name). When framers are used a lot, I can envision that at some point a message might not use data bytes at all any more, as all information in the underlying message is being dissected into protocol specific properties.
To give a bit of more context here: The protocol(s) I have in mind to implement in terms of TAPS is the CoAP family, which is currently specified for UDP, TCP and WebSockets transports. TCP and WebSockets would work well with framers that get data down to messages, but a first "layer" of framers would still produce different styles of messages -- concretely, the native UDP datagrams contain bytes [something, code, message-id, token, options, payload] whereas after a layer of de-framing TCP, what is left is [code, token, options, payload] plus an additional property (token length) that is extracted from a nibble in the framing. To make these messages usable more universally (i.e. independently of their transport), it'd make sense to de-frame these again (including de-framing the UDP messages) into decoding even more, moving code, token and options into properties. In the end, that will often result in messages that look like empty messages with a lot of properties -- is that OK? Would they even necessarily have a zero-length payload (byte-style message data)? Is the message's data just a (maybe special, maybe not) property of the message?
Messages can certainly be empty, and instead only contain Message Properties stored in the Message Context. We can make it clear that this is possible in section 5.2 of implementation.
LGTM. NAME says that text will be needed in the API draft to state that Messages can be empty.

I'm not sure this is really necessary to add there; it wouldn't hurt, but it also doesn't get in the way of merging this PR.This text looks fine to me, but as discussed some complementing text about the possibility of a messageData object being empty will be needed in the API draft.